﻿using ErrorOr;
using Gym.Application.Common.Interfaces;
using Gym.Domain.Common.Interfaces;
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gym.Application.Participants.Commands.CancelReservation
{
    public class CancelReservationCommandHandler : IRequestHandler<CancelReservationCommand, ErrorOr<Deleted>>
    {
        private readonly ISessionsRepository _sessionsRepository;
        private readonly IParticipantsRepository _participantsRepository;
        private readonly IDateTimeProvider _dateTimeProvider;

        public CancelReservationCommandHandler(ISessionsRepository sessionsRepository, IParticipantsRepository participantsRepository, IDateTimeProvider dateTimeProvider)
        {
            _sessionsRepository = sessionsRepository;
            _participantsRepository = participantsRepository;
            _dateTimeProvider = dateTimeProvider;
        }

        public async Task<ErrorOr<Deleted>> Handle(CancelReservationCommand request, CancellationToken cancellationToken)
        {
            var session = await _sessionsRepository.GetByIdAsync(request.SessionId);
            
            if (session is null)
            {
                return Error.NotFound(description: "没有找到该课程信息");
            }
            
            if(!session.HasReservationForParticipant(request.ParticipantId))
            {
                return Error.NotFound(description: "没有找到该用户预约信息");
            }

            var participant = await _participantsRepository.GetByIdAsync(request.ParticipantId);

            if (participant is null)
            {
                return Error.NotFound(description: "没有找到该用户信息");
            }

            if(!participant.HasReservationForSession(session.Id))
            {
                return Error.Unexpected(description: "该用户没有预约该课程");
            }

            var cancelReservationResult = session.CancelReservation(participant, _dateTimeProvider);

            if (cancelReservationResult.IsError)
            {
                return cancelReservationResult.Errors;
            }

            await _sessionsRepository.UpdateAsync(session);

            return Result.Deleted;
        }
    }
}
